home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------*/
- /* */
- /* MC68000 Cross Assembler */
- /* */
- /* Copyright (c) 1985 by Brian R. Anderson */
- /* */
- /* Miscellaneous routines - September 8, 1987 */
- /* */
- /* This program may be copied for personal, non-commercial use */
- /* only, provided that the above copyright notice is included */
- /* on all copies of the source code. Copying for any other use */
- /* without the consent of the author is prohibited. */
- /* */
- /*------------------------------------------------------------------*/
- /* */
- /* Originally published (in Modula-2) in */
- /* Dr. Dobb's Journal, April, May, and June 1986. */
- /* */
- /* AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs. */
- /* */
- /*------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include "a68kdef.h"
- #include "a68kglb.h"
-
- char Sdata[MAXSREC]; /* S-record data */
- int Sindex; /* Index for Sdata */
- int NumRExt, NumR32, NumR16, NumR8;
-
- static char *errmsg[] = {
- "--- Unknown error code ---",
- "Identifier too long -- Truncated!",
- "No such op-code.",
- "Duplicate Symbol.",
- "Undefined Symbol.",
- "Addressing mode not allowed here.",
- "Error in operand format.",
- "Error in relative branch.",
- "Address mode error.",
- "Operand size error.",
- "END statement is missing.",
- "Value must be absolute.",
- "Relocatability error.",
- "Too many nested INCLUDEs.",
- "INCLUDE file cannot be opened.",
- "Illegal forward reference.",
- "Not supported in S-format.",
- "This instruction needs a label.",
- "Pass 1 / Pass 2 phase error.",
- "ENDM statement is missing.",
- "Too much DC data.",
- "Too many SECTIONs.",
- "Section may not be unnamed.",
- "Wrong type in continuation.",
- "Duplicate macro definition.",
- ""};
-
- /* Functions */
- extern int LineParts(), GetField(), Instructions(), ObjDir();
- extern int GetSize(), GetInstModeSize(), GetMultReg();
- extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl();
- extern long GetValue(), CalcValue();
- extern char *malloc();
- extern FILE *fopen();
-
- long AddrBndW(), AddrBndL();
-
-
-
- long AddrBndW (v) long v;
- /* Advances "v" to the next word boundary */
- {
- if (v & 1L) {
- AppendSdata (Srec, 0L, 1);
- v++;
- }
- return (v);
- }
-
-
-
- long AddrBndL (v) long v;
- /* Advances "v" to the next long-word boundary */
- {
- long templong;
-
- v = AddrBndW (v); /* Bump to word boundary first */
- if (v & 2L) { /* If still not aligned, */
- templong = NOP; /* generate a NOP */
- AppendSdata (Srec, templong, 2);
- v += 2;
- }
- return (v);
- }
-
-
-
- WriteListLine (f) FILE *f;
- /* Writes one line to the Listing file, including Object Code */
- {
- register int i, j;
- long templong;
- char macflag;
-
- if (errlim == 0)
- if ((Dir == Page) || (Dir == Space) || (Dir == Title)
- || (Dir == DoList) || (Dir == NoList) || (ListOff))
- return; /* Don't print unless they have errors */
-
- CheckPage (f, FALSE); /* Print headings if necessary */
-
- if (PrntAddr) {
- if ((Dir == Equ) || (Dir == Set))
- LongPut (f, ObjSrc, 3); /* Equated value */
- else
- LongPut (f, AddrCnt, 3); /* Current location */
- fprintf (f, " ");
- } else
- fprintf (f, " "); /* Don't print location */
- LongPut (f, ObjOp, nO); /* Generated code */
- if (nS != 0) {
- fprintf (f, " ");
- LongPut (f, ObjSrc, nS);
- }
- if (nD != 0) {
- fprintf (f, " ");
- LongPut (f, ObjDest, nD);
- }
- if ((j = nX) > 0) { /* String data */
- if ((j + nO + nS + nD) > 12)
- j = 12 - nO - nS - nD;
- for (i = 0; i < j; i++) {
- templong = ObjString[i];
- LongPut (f, templong, 1);
- }
- }
- i = 6 + (nO + nS + nD + j) * 2; /* Hex digits printed */
- if (nS != 0) i++; /* Space between operands */
- if (nD != 0) i++;
- while (i < ObjMAX) {
- fprintf (f, " ");
- i++;
- }
- if ((InFNum == 0) || (OuterMac == 0))
- macflag = ' '; /* Open code */
- else if (InFNum > OuterMac)
- macflag = '+'; /* Inner macro */
- else if ((InFNum == OuterMac) && (Dir != MacCall))
- macflag = '+'; /* Outermost macro */
- else
- macflag = ' '; /* We're outside macros */
-
- fprintf (f, " %4d%c%s\n", LineCount, macflag, Line);
-
- for (i = 0; i < errlim; i++) { /* Write error messages. */
- CheckPage (f, FALSE);
- fprintf (f, "%s", errmsg[errcode[i]]);
- for (j=strlen(errmsg[errcode[i]]); j<ObjMAX+8+errpos[i]; j++)
- fprintf (f, " ");
- fprintf (f, "^ "); /* Error flag */
- if (i == 0) {
- if (InF->UPtr == 0)
- fprintf (f, "%s", InF->NPtr); /* Module name */
- else
- fprintf (f, "(user macro)"); /* In a user macro */
- fprintf (f, " line %d", InF->Line); /* Line number */
- }
- fprintf (f, "\n");
- }
- }
-
-
-
- WriteSymTab (f) FILE *f;
- /* Lists symbol table in alphabetical order */
- {
- int printhunk, i;
- char *p;
- register int j, k;
- struct SymTab *sym;
- struct Ref *ref;
-
- LnCnt = 999; /* Skip to a new page. */
- for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
- CheckPage (f, TRUE);
-
- p = sym->Nam; /* Pointer to symbol */
- while (*p == ' ') /* Skip leading blanks, if any */
- p++;
- fprintf (f, "%-11s ", p); /* Symbol or macro name */
- if (strlen (p) > 11) /* Long symbol - go to new line */
- fprintf (f, "\n ");
-
- printhunk = FALSE; /* Assume no hunk no. to print */
- if (sym->Defn == 0)
- fprintf (f, " *** UNDEFINED *** ");
- else if (sym->Flags & 4)
- fprintf (f, " -- SET Symbol -- ");
- else if (sym->Flags & 8)
- fprintf (f, " +++ MACRO +++ %4d", sym->Defn);
- else if (sym->Flags & 0x10) {
- fprintf (f, " SECTION ");
- printhunk = TRUE;
- } else if (sym->Flags & 0x20) {
- fprintf (f, " %c", (sym->Val & 8) ? 'A' : 'D');
- fprintf (f, "%d ", sym->Val & 7);
- printhunk = TRUE;
- } else {
- LongPut (f, sym->Val, 4); /* Value */
- fprintf (f, " ");
- printhunk = TRUE;
- }
- if (printhunk) {
- j = sym->Hunk & 0x00007FFFL; /* Hunk number */
- if (sym->Flags & 0x60)
- fprintf (f, " Reg"); /* Register or list */
- else if (sym->Hunk & 0x00008000L)
- fprintf (f, " Ext"); /* External */
- else if (j == ABSHUNK)
- fprintf (f, " Abs"); /* Absolute */
- else
- fprintf (f, "%4d", j); /* Hunk number */
- fprintf (f, " %4d", sym->Defn); /* Statement no. */
- }
- if (XrefList) {
- fprintf (f, " ");
- if (sym->Ref1 == 0)
- fprintf (f, " *** UNREFERENCED ***");
- else {
- ref = sym->Ref1;
- j = k = 0;
- while (1) {
- if (ref->RefNum[j] == 0)
- break;
- if (k >= 9) {
- fprintf (f, "\n"); /* New line */
- for (k = 0; k < 34; k++)
- fprintf (f, " ");
- k = 0;
- }
- fprintf (f, " %4d", ref->RefNum[j]);
- j++;
- k++;
- if (j < MAXREF)
- continue; /* Get the next slot */
- if ((ref = ref->NextRef) == 0)
- break; /* End of last entry */
- j = 0; /* Start the next entry */
- }
- }
- }
- fprintf (f, "\n");
- }
- }
-
-
-
- CheckPage (f, xhdr) FILE *f; int xhdr;
- /* Checks if end of page reached yet -- if so, advances to next page. */
- {
- LnCnt++;
- if (LnCnt >= LnMax) {
- PgCnt++;
- if (PgCnt > 1)
- fprintf (f, "\f"); /* Skip to new page */
- fprintf (f, "%-50s", TTLstring); /* Title */
- fprintf (f, " %s ", SourceFN); /* File name */
- fprintf (f, "Page %d\n\n\n", PgCnt); /* Page number */
- LnCnt = 3;
- if (xhdr) {
- fprintf (f, "Symbol Value Hunk Line");
- if (XrefList)
- fprintf (f, " References"); /* Cross-reference */
- fprintf (f, "\n\n");
- LnCnt += 2;
- }
- }
- }
-
-
-
- StartSrec (f, idntname) FILE *f; char idntname[];
- /* Writes object header record */
- {
- register int i;
- long CheckSum, templong;
-
- if (SFormat) {
- fprintf (f, "S0");
- templong = strlen (idntname) + 3; /* extra for addr. & checksum */
- LongPut (f, templong, 1);
- CheckSum = templong;
-
- fprintf (f, "0000"); /* Address is 4 digits, all zero, for S0 */
-
- for (i = 0; idntname[i] != '\0'; i++) {
- templong = toupper (idntname[i]);
- LongPut (f, templong, 1);
- CheckSum += templong;
- }
- CheckSum = ~CheckSum; /* Complement checksum */
- LongPut (f, CheckSum, 1);
- fprintf (f, "\n");
- } else {
- templong = HunkUnit;
- putl (f, templong);
- DumpName (f, idntname, 0L);
- }
- StartAddr = TempAddr = Sindex = 0;
- NumRExt = NumR32 = NumR16 = NumR8 = 0;
- }
-
-
-
- WriteSrecLine (f) FILE *f;
- /* Transfers object code components to output buffer. */
- /* Moves long words or portions thereof. */
- {
- register int i;
- long templong;
-
- if (HunkType == HunkBSS)
- return; /* No code in BSS hunk */
-
- if (nO + nS + nD + nX) { /* If we have object code */
- if (AddrCnt < TempAddr) { /* and location counter jumped */
- if (SFormat) /* and we're making S-format, */
- DumpSdata (f); /* get rid of what we have */
- StartAddr = TempAddr = AddrCnt; /* and start afresh. */
- }
- while (AddrCnt >= (TempAddr + 4)) /* It jumped forward - */
- AppendSdata (f, 0L, 4); /* fill with zeros */
- if (AddrCnt > TempAddr) {
- i = AddrCnt - TempAddr;
- AppendSdata (f, 0L, i);
- }
- AppendSdata (f, ObjOp, nO); /* Op code */
- AppendSdata (f, ObjSrc, nS); /* Source */
- AppendSdata (f, ObjDest, nD); /* Destination */
- for (i = 0; i < nX; i++) { /* String data */
- templong = ObjString[i];
- AppendSdata (f, templong, 1);
- }
- }
- }
-
-
-
- AppendSdata (f, Data, n) FILE *f; long Data; int n;
- /* If we are producing S-format records:
- Transfers "n" low-order bytes from "Data" to the output buffer.
- If the buffer becomes full, DumpSdata will be called to flush it.
- S-records will also be broken on 16-byte boundaries.
- If we are producing AmigaDOS format, data will be written
- directly to Srec - we'll go back and fill in the hunk length
- at the end of the hunk. */
- {
- register int i;
- register char byte;
- long templong;
-
- if (!Pass2)
- return; /* Pass 2 only */
- if (HunkType == HunkBSS)
- return; /* No data in BSS hunks! */
-
- if (HunkType == HunkNone) { /* We're not in a hunk yet - */
- ReadSymTab (" "); /* set up pointer */
- Sect = Sym; /* to the first section */
- HunkType = HunkCode; /* (start a code hunk) */
- SectLine = LineCount;
- if (!SFormat) {
- templong = HunkName;
- putl (f, templong);
- DumpName (f, " ", 0L);
- putl (f, HunkType);
- LenPos = ftell (f); /* Hunk length goes here when we get it */
- putl (f, 0L); /* For now, set it to zero */
- }
- }
-
- Data <<= (4 - n) * 8; /* Left-justify data */
-
- for (i = 0; i < n; i++) {
- byte = (Data >> ((3 - i) * 8)) & 0x00FF;
- TempAddr++;
- if (!SFormat)
- putc (byte, f);
- else {
- Sdata[Sindex++] = byte;
- if (((TempAddr & 0x0F) == 0) || (Sindex >= MAXSREC))
- DumpSdata (f); /* Break S-record */
- }
- }
- }
-
-
-
- DumpSdata (f) FILE *f;
- /* Writes an object code record */
- {
- register int i;
- register long CheckSum, templong;
-
- if (!SFormat) {
- AddrCnt = AddrBndL (AddrCnt); /* Finish last long word */
- fseek (f, LenPos, 0); /* Hunk length field is here */
- putl (f, ((AddrCnt - SectStart) >> 2) | HunkFlags);
- fseek (f, 0L, 2); /* Back to end of file */
- DumpRel (f); /* Write relocation information */
- TempAddr = AddrCnt;
- return;
- }
-
- if (Sindex == 0)
- return; /* There's nothing to dump */
-
- fprintf (f, "S2");
- templong = Sindex + 4; /* Record length */
- LongPut (f, templong, 1);
- CheckSum = templong; /* Initialize CheckSum */
-
- LongPut (f, StartAddr, 3); /* Address */
- CheckSum += (StartAddr >> 16) & 0x00FF;
- CheckSum += (StartAddr >> 8) & 0x00FF;
- CheckSum += StartAddr & 0x00FF;
-
- for (i = 0; i < Sindex; i++) {
- templong = Sdata[i];
- LongPut (f, templong, 1); /* Object code */
- CheckSum += templong;
- }
- CheckSum = ~CheckSum; /* Complement checksum */
- LongPut (f, CheckSum, 1);
- fprintf (f, "\n");
-
- StartAddr += Sindex;
- TempAddr = StartAddr;
- Sindex = 0;
- }
-
-
-
- PutRel (f, addr, hunk, size) FILE *f; long addr, hunk; int size;
- /* Build a relocation entry if necessary */
- {
- struct RelTab *rel;
-
- if (!Pass2) return; /* Pass 2 only */
- if (SFormat) return; /* Not for S-format! */
- if (hunk == ABSHUNK) return; /* Absolute */
- if (HunkType == HunkBSS) return; /* Not for BSS hunks! */
-
- HeapSpace (sizeof(struct RelTab)); /* Make sure we have room */
- rel = (struct RelTab *) HeapLim; /* Pointer to new entry */
- rel->Offset = addr; /* Offset */
- rel->Hunk = hunk; /* Hunk number */
- rel->Size = size; /* Size */
- HeapLim += sizeof(struct RelTab); /* Bump heap limit pointer */
-
- if (hunk < 0) /* Count entries by type */
- NumRExt++;
- else if (size == Long)
- NumR32++;
- else if (size == Word)
- NumR16++;
- else
- NumR8++;
- }
-
-
-
- DumpRel (f) FILE *f;
- /* Dump relocation information to the object file. */
- {
- register struct SymTab *sym;
- register struct RelTab *rel, *rel2;
- int i, j, size, num, donexhdr, secthlin;
- long currhunk, nexthunk, templong;
- char *p;
-
- if (SFormat)
- return; /* S-format is absolute! */
-
- secthlin = LineCount; /* Current section ends here */
- if (strcmp (OpCode,"SECTION") == 0) /* unless we're starting */
- secthlin--; /* a new section. */
-
- while (1) {
- if ((num = NumR32) != 0) {
- size = Long; /* Do 32-bit fields */
- templong = HunkR32;
- NumR32 = 0; /* ...but only once */
- } else if ((num = NumR16) != 0) {
- size = Word; /* Then do 16-bit fields */
- templong = HunkR16;
- NumR16 = 0;
- } else if ((num = NumR8) != 0) {
- size = Byte; /* Finally do 8-bit fields */
- templong = HunkR8;
- NumR8 = 0;
- } else
- break; /* We're all done */
-
- putl (f, templong); /* Record type */
-
- currhunk = 32767;
- num = 0;
- for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
- if ((rel->Size == size) && (rel->Hunk >= 0)) {
- if (rel->Hunk < currhunk) {
- currhunk = rel->Hunk; /* Lowest hunk number */
- num = 1; /* Reset counter */
- } else if (rel->Hunk == currhunk) {
- num++; /* Count entries */
- }
- }
- }
- while (num > 0) { /* Repeat for all hunk references */
- templong = num;
- putl (f, templong); /* Number of entries */
- putl (f, currhunk); /* Hunk number */
- nexthunk = 32767;
- num = 0; /* Count for next hunk */
- for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
- if ((rel->Size == size) && (rel->Hunk >= 0)) {
- if (rel->Hunk < currhunk)
- continue; /* Already wrote it */
- else if (rel->Hunk == currhunk)
- putl (f, rel->Offset - Sect->Val);
- else if (rel->Hunk < nexthunk) {
- nexthunk = rel->Hunk; /* Next hunk number */
- num = 1; /* Reset counter */
- } else if (rel->Hunk == nexthunk) {
- num++; /* Count entries */
- }
- }
- }
- currhunk = nexthunk; /* Get ready for next hunk */
- }
- putl (f, 0L); /* End of relocation information */
- }
-
- donexhdr = FALSE; /* Haven't written hunk_ext yet */
-
- for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
- if (sym->Flags & 2) { /* Scan for XDEF symbols */
- j = sym->Defn; /* Defined in current section? */
- if ((j >= SectLine) && (j <= secthlin)) {
- if (!donexhdr) {
- templong = HunkExt; /* Haven't done header yet */
- putl (f, templong);
- donexhdr = TRUE;
- }
- if ((sym->Hunk & 0x0000FFFFL) == ABSHUNK)
- templong = 0x02000000;
- else
- templong = 0x01000000; /* Flags */
- DumpName (f, sym->Nam, templong); /* Symbol */
- putl (f, sym->Val - Sect->Val); /* Offset */
- }
- }
- }
-
- if (NumRExt != 0) { /* External references (XREF) */
- if (!donexhdr) {
- templong = HunkExt; /* Haven't done header yet */
- putl (f, templong);
- donexhdr = TRUE;
- }
- for (rel = RelStart; rel < (struct RelTab *) HeapLim; rel++) {
- if (rel->Hunk < 0) {
- p = Heap + ~rel->Hunk;
- if (rel->Size == Long)
- templong = 0x81000000; /* ext_ref32 */
- else if (rel->Size == Word)
- templong = 0x83000000; /* ext_ref16 */
- else
- templong = 0x84000000; /* ext_ref8 */
- DumpName (f, p, templong); /* Flags and symbol */
- templong = 1;
- for (rel2 = rel + 1; rel2 < (struct RelTab *) HeapLim; rel2++)
- if (rel2->Hunk == rel->Hunk)
- templong++; /* Number of times */
- putl (f, templong); /* symbol occurs */
- for (rel2 = rel; rel2 < (struct RelTab *) HeapLim; rel2++) {
- if (rel2->Hunk == rel->Hunk) {
- putl (f, rel2->Offset - Sect->Val); /* Offset */
- if (rel2 != rel) /* Kill hunk so we */
- rel2->Hunk = 0; /* don't do it again */
- } /* (we're done with */
- } /* the table anyway) */
- }
- }
- NumRExt = 0;
- }
- if (donexhdr)
- putl (f, 0L); /* End of external information */
-
- if (DumpSym) { /* Dump the symbol table */
- donexhdr = FALSE;
- for (i = 0, sym = SymStart; i < NumSyms; i++, sym++) {
- if ((sym->Hunk == CurrHunk)
- && ((sym->Flags == 0) || (sym->Flags == 2))) {
- j = sym->Defn; /* Defined in current section? */
- if ((j >= SectLine) && (j <= secthlin)) {
- if (!donexhdr) {
- templong = HunkSym; /* Header */
- putl (f, templong);
- donexhdr = TRUE;
- }
- DumpName (f, sym->Nam, 0L); /* Symbol */
- putl (f, sym->Val - Sect->Val); /* Offset */
- }
- }
- }
- if (donexhdr)
- putl (f, 0L); /* End of symbol table dump */
- }
-
- if (HeapLim > HighHeap)
- HighHeap = HeapLim; /* High-water mark */
- HeapLim = (char *) RelStart; /* Reset heap limit */
- }
-
-
-
- EndSdata (f, addr) FILE *f; long addr;
- /* Write end record to object file */
- {
- register long checksum, templong;
-
- if (SFormat) {
- DumpSdata (Srec); /* Write any remaining data */
- fprintf (f, "S804"); /* Record header */
- checksum = 4;
- LongPut (f, addr, 3); /* Transfer address */
- checksum += (addr >> 16) & 0x00FF;
- checksum += (addr >> 8) & 0x00FF;
- checksum += addr & 0x00FF;
- checksum = ~checksum;
- LongPut (f, checksum, 1); /* Checksum */
- fprintf (f, "\n");
- } else {
- if (HunkType != HunkNone) {
- DumpSdata (Srec); /* Last hunk's data */
- templong = HunkEnd; /* End the last hunk */
- putl (f, templong);
- }
- }
- }
-
-
-
- DumpName (f, name, flags) FILE *f; char name[]; long flags;
- /* Writes a name preceded by a long word containing the
- length of the name in long words. The length word has
- the contents of "flags" ORed into it. The name is padded
- with binary zeros to the next long word boundary. */
- {
- register int i;
- register long templong;
-
- templong = (strlen (name) + 3) >> 2; /* Length (long words) */
- templong |= flags; /* Add flag bits */
- putl (f, templong);
- i = 0;
- while (name[i])
- putc (name[i++], f); /* Write a byte */
- while (i & 3) {
- putc ('\0', f); /* Pad the last word */
- i++;
- }
- }
-
-
-
- LongPut (f, data, length) FILE *f; long data; int length;
- /* Writes to file "f" the hexadecimal interpretation of
- the bytes in "data". The number of bytes written
- (two hex digits per byte) is given in "length" -
- if less than 4, only low-order bytes are written. */
- {
- register int i, j, k;
-
- for (i = length - 1; i >= 0; i--) {
- j = (data >> (i * 8)) & 0x00FF;
- k = j >> 4;
- fprintf (f, "%c", k>9 ? k-10+'A' : k+'0');
- k = j & 0x0F;
- fprintf (f, "%c", k>9 ? k-10+'A' : k+'0');
- }
- }
-
-
-
- putl (f, data) FILE *f; long data;
- /* Writes to file "f" the binary contents of "data" */
- {
- register int i;
- register char byte;
-
- for (i = 0; i < 4; i++) {
- byte = (data >> ((3 - i) * 8)) & 0x00FF;
- putc (byte, f);
- }
- }
-
-
-
- Error (pos, errornum) int pos, errornum;
- /* Displays error #errornum, then waits for any key to continue */
- {
- register int i;
-
- if (!Pass2)
- return; /* Active during pass 2 only */
-
- if (errlim < ERRMAX) { /* Save error data */
- errcode[errlim] = errornum;
- errpos[errlim] = pos;
- errlim++;
- }
- printf (" \n%4d %s\n", LineCount, Line); /* Line in error */
- for (i = 0; i < pos+7; i++)
- printf(" ");
- printf ("^ "); /* Error flag */
- if (errlim == 1) {
- if (InF->UPtr == 0)
- printf ("%s", InF->NPtr); /* Module name */
- else
- printf ("(user macro)"); /* In a user macro */
- printf (" line %d", InF->Line); /* Line number in module */
- }
- printf ("\n%s\n", errmsg[errornum]); /* Error message */
- ErrorCount++; /* Count errors */
- }
-